﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 
// See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Fabric;
using System.Fabric.Description;
using System.Reflection;
using System.IO;
using System.Diagnostics.Contracts;

namespace System.Threading.Actors
{
    // This class is the base class upon which ad-hoc actors should be based.
    public class FabricAdHocActorBase
    {
        private readonly string m_actorName;
        private readonly string m_appName = "fabric:/actor/adhoc";
        private readonly string m_serviceName;

        public string ActorName { get { return m_actorName; } }
        public FabricAdHocActorBase(string actorName)
        {
            m_actorName = actorName;
            m_serviceName = String.Format("{0}/{1}", m_appName, actorName);
        }

        // Use this routine to deploy an actor/service for the first time, and to get a client to it.
        public FabricActorClient DeployAndConnect(string fabricConnectionString, bool useGateway, int numReplicas)
        {
            Contract.Requires(numReplicas >= 1);

            try
            {
                FabricActorClient.CreateActor(
                    fabricConnectionString,
                    m_appName,
                    m_serviceName,
                    "EmptyActorReplica",
                    numReplicas);
            }
            catch (AggregateException ae)
            {
                // Ignore exception for already-existing actor
                if (!ae.Flatten().InnerExceptions.Any(e => e is FabricElementAlreadyExistsException))
                    throw;
            }

            // TODO: Wait for service/actor to actually launch
            Uri fabricUri = new Uri("net.tcp://" + fabricConnectionString);
            var actorClient = Connect(fabricUri, new Uri(m_serviceName), useGateway);
            return actorClient;
        }

        public FabricActorClient Connect(Uri fabricUri, Uri actorUri, bool useGateway)
        {
            return new FabricActorClient(fabricUri, actorUri, useGateway);
        }
    }
}